/**
 * 历史记录管理模块
 */
export default class HistoryManager {
  constructor(maxLength = 20) {
    this.undoList = []
    this.redoList = []
    this.maxLength = maxLength
  }

  /**
   * 添加历史记录
   * @param {string} type 操作类型
   * @param {object} json 状态数据
   * @returns {boolean} 是否添加成功
   */
  addHistory(type, json) {
    // 将操作类型和状态一起记录到历史
    const historyItem = JSON.stringify({ lastType: type, lastJson: json })
    
    // 检查是否与最近的历史记录重复
    const lastRecord = this.undoList[this.undoList.length - 1]
    if (lastRecord) {
      const { lastType, lastJson } = JSON.parse(lastRecord)
      // 如果当前操作与最近的历史记录完全相同，则不重复记录
      if (lastType === type && JSON.stringify(lastJson) === JSON.stringify(json)) {
        return false
      }
    }

    this.undoList.push(historyItem)
    // 如果撤销栈超过最大长度，移除最早的记录
    if (this.undoList.length > this.maxLength) {
      this.undoList.shift()
    }
    // 添加新的历史记录时，不再清空重做栈，而是保持现有的重做记录
    return true
  }

  /**
   * 撤销操作
   * @returns {object|null} 返回上一个状态，如果没有则返回null
   */
  undo() {
    if (this.undoList.length > 0) {
      const lastState = this.undoList.pop()
      const { lastJson } = JSON.parse(lastState)
      // 将当前状态添加到重做栈，并确保不超过最大长度
      this.redoList.push(lastState)
      if (this.redoList.length > this.maxLength) {
        this.redoList.shift()
      }
      return lastJson
    }
    return null
  }

  /**
   * 重做操作
   * @returns {object|null} 返回下一个状态，如果没有则返回null
   */
  redo() {
    if (this.redoList.length > 0) {
      const nextState = this.redoList.pop()
      const { lastJson } = JSON.parse(nextState)
      // 将当前状态添加到撤销栈，并确保不超过最大长度
      this.undoList.push(nextState)
      if (this.undoList.length > this.maxLength) {
        this.undoList.shift()
      }
      return lastJson
    }
    return null
  }

  /**
   * 获取撤销栈长度
   * @returns {number}
   */
  get undoLength() {
    return this.undoList.length
  }

  /**
   * 获取重做栈长度
   * @returns {number}
   */
  get redoLength() {
    return this.redoList.length
  }

  /**
   * 清空历史记录
   */
  clear() {
    this.undoList = []
    this.redoList = []
  }
}